Docker Compose 实战:搭建 LNMP 环境

本文摘要背景LNMP(Linux + Nginx + MySQL + PHP)是 PHP 开发者最熟悉的环境组合。虽然在服务器上手搓安装也不算难,但换服务器、换系统、或者想快速搭建一套开发环境时,重复操作还是挺烦人的。恰好博客目前跑在 Docker 上(参见《Docker 化部署 Typecho 完整指南》),所以这套 LNMP 也用 Docker Compose 来编排,干净、可复现、随时拆掉重来。环境...

cover

背景

LNMP(Linux + Nginx + MySQL + PHP)是 PHP 开发者最熟悉的环境组合。虽然在服务器上手搓安装也不算难,但换服务器、换系统、或者想快速搭建一套开发环境时,重复操作还是挺烦人的。

恰好博客目前跑在 Docker 上(参见《Docker 化部署 Typecho 完整指南》),所以这套 LNMP 也用 Docker Compose 来编排,干净、可复现、随时拆掉重来。

环境规划

这套方案的目标:在单台服务器上用 Docker Compose 跑起 LNMP,能跑多个 PHP 站点,PHP 和 Nginx 分开容器,方便单独调整。

服务组成

服务镜像用途
nginxnginx:stable-alpineWeb 服务器 / 反向代理
phpphp:8.2-fpm-alpinePHP 解析
mysqlmysql:8.0数据库
phpmyadminphpmyadmin:latest数据库管理(可选,开发环境用)

目录结构

~/lnmp/
├── docker-compose.yml
├── nginx/
│   ├── conf.d/
│   │   └── default.conf
│   └── html/
│       └── index.php
├── php/
│   └── php.ini
└── mysql/
    └── data/          # 数据持久化目录

部署步骤

第一步:创建目录结构和配置文件

mkdir -p ~/lnmp/{nginx/conf.d,nginx/html,php,mysql/data}
cd ~/lnmp

第二步:编写 docker-compose.yml

version: "3.8"

services:
  nginx:
    image: nginx:stable-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/html:/var/www/html
      - ./php:/var/www/php
    depends_on:
      - php
    networks:
      - lnmp

  php:
    image: php:8.2-fpm-alpine
    volumes:
      - ./nginx/html:/var/www/html
      - ./php/php.ini:/usr/local/etc/php/php.ini
    expose:
      - "9000"
    networks:
      - lnmp

  mysql:
    image: mysql:8.0
    ports:
      - "3306:3306"
    volumes:
      - ./mysql/data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: <your-mysql-root-password>
      MYSQL_DATABASE: app
      MYSQL_USER: app_user
      MYSQL_PASSWORD: <your-app-user-password>
    networks:
      - lnmp

  phpmyadmin:
    image: phpmyadmin:latest
    ports:
      - "8080:80"
    environment:
      PMA_HOST: mysql
      PMA_PORT: 3306
    depends_on:
      - mysql
    networks:
      - lnmp

networks:
  lnmp:

几个设计要点:

  • Nginx 和 PHP 通过容器网络通信,Nginx 通过 php:9000 地址转发给 FPM,不暴露 PHP 端口到宿主机
  • MySQL 暴露了 3306 端口,方便用 Navicat 等客户端连接;如果不需要外连,去掉 ports 字段只保留 expose
  • phpMyAdmin 开在 8080 端口,开发环境方便操作数据库,线上环境建议去掉
  • 数据库的 root 密码和应用用户密码放在环境变量里,线上请改用 .env 文件

第三步:配置 Nginx

nginx/conf.d/default.conf

server {
    listen 80;
    server_name localhost;
    root /var/www/html;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass   php:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www/html$fastcgi_script_name;
        include        fastcgi_params;
    }
}

注意 fastcgi_pass 写的是 php:9000——因为 Compose 中服务名叫 php,Docker 内部 DNS 会自动解析。

第四步:PHP 配置

php/php.ini(只列出几个常用参数,其余用默认值):

upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
date.timezone = Asia/Shanghai

第五步:启动

docker compose up -d

查看启动状态:

docker compose ps

预期输出四个服务都是 Up 状态。

第六步:验证

创建一个测试文件 nginx/html/index.php

<?php
phpinfo();

浏览器访问 http://<服务器IP>,应该能看到 PHP 信息页面。往下翻到数据库部分,确认 MySQL 连接正常。

也可以写个简单的连接测试:

<?php
$host = 'mysql';
$user = 'app_user';
$pass = '<your-app-user-password>';
$db   = 'app';

try {
    $pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8mb4", $user, $pass);
    echo '数据库连接成功';
} catch (PDOException $e) {
    echo '连接失败: ' . $e->getMessage();
}

mysql 这个主机名能连接上,说明 Docker 内部网络通了。

部署多个站点

同一台服务器上想跑多个 PHP 站点,只需在 nginx/conf.d/ 下加新的 .conf 文件:

server {
    listen 80;
    server_name blog.cndoor.vip;
    root /var/www/blog;
    index index.php index.html;

    location ~ \.php$ {
        fastcgi_pass   php:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www/blog$fastcgi_script_name;
        include        fastcgi_params;
    }
}

把站点文件放到对应的根目录(如 nginx/html/blog/),然后 reload Nginx:

docker compose exec nginx nginx -s reload

总结

这套 LNMP 方案的优势:

  • 环境隔离——每个服务独立容器,互不干扰
  • 可复现——一个 docker compose up -d 就能在新服务器上拉起整套环境
  • 易于扩展——加站点就是加配置文件,不需要动 Nginx 主配置
  • 不影响宿主机——不想用了 docker compose down -v 即可清理

推荐做法

  1. 线上环境去掉 phpMyAdmin 容器
  2. 数据库密码用 .env 文件管理,不要硬编码在 docker-compose.yml 里
  3. PHP 和 Nginx 分开容器是对的——升级 PHP 版本时只需改镜像标签重启一个容器
  4. MySQL 数据目录 ./mysql/data 要定期备份

参考

觉得内容不错?我要

评论 暂无评论
暂无评论,快来抢沙发吧~